package com.dcy.znoa.service.software.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.dcy.znoa.common.enums.OperTypeCode;
import com.dcy.znoa.common.enums.ResultCode;
import com.dcy.znoa.common.exception.BusinessException;
import com.dcy.znoa.dao.publiz.CompanyDao;
import com.dcy.znoa.dao.publiz.DepartmentDao;
import com.dcy.znoa.dao.publiz.DutyDao;
import com.dcy.znoa.dao.sys.OperRoleDao;
import com.dcy.znoa.dao.sys.UrlListDao;
import com.dcy.znoa.dao.user.OperDao;
import com.dcy.znoa.dao.user.OperSessionDao;
import com.dcy.znoa.domain.Oper;
import com.dcy.znoa.domain.OperSession;
import com.dcy.znoa.domain.publiz.Company;
import com.dcy.znoa.domain.publiz.Department;
import com.dcy.znoa.domain.publiz.Duty;
import com.dcy.znoa.domain.sys.OperRole;
import com.dcy.znoa.domain.sys.UrlListTreeVo;
import com.dcy.znoa.service.dic.AreaService;
import com.dcy.znoa.service.software.SessionService;
import com.dcy.znoa.service.software.OperService;
import com.google.common.base.Preconditions;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
public class SessionServiceImpl implements SessionService {

    @Autowired
    OperSessionDao userSessionDao;

    @Autowired
    OperService userService;

    @Autowired
    DutyDao dutyDao;
    @Autowired
    CompanyDao companyDao;
    @Autowired
    DepartmentDao departmentDao;
    @Autowired
    OperDao operDao;
    @Autowired
    AreaService areaService;
    @Autowired
    UrlListDao urlListDao;
    @Autowired
    OperRoleDao operRoleDao;

    private static final long MAX_ALIVE_MILLS = 1000 * 60 * 60 * 24;

    //modified by chenjie
    @Override
    public OperSession touchSession(Long sid, String token) throws BusinessException {
        Preconditions.checkNotNull(sid);
        Preconditions.checkNotNull(token);
        OperSession userSession = userSessionDao.selectById(sid);
        if (!token.equals(userSession.getToken())) {
            throw new BusinessException(ResultCode.SESSION_EXPIRED);
        }
        if (userSession.getExitTime() != null) {
            throw new BusinessException(ResultCode.SESSION_EXPIRED);
        }
        if ((System.currentTimeMillis() - userSession.getLastAccessTime().getTime()) >= MAX_ALIVE_MILLS) {
            //如果超时，则拔退出时间写为最后一次访问时间 + session最长有效时间
            userSession.setExitTime(new Date(userSession.getLastAccessTime().getTime() + MAX_ALIVE_MILLS));
            throw new BusinessException(ResultCode.SESSION_EXPIRED);
        }
        userSession.setLastAccessTime(new Date());
        userSessionDao.updateById(userSession);

        Oper oper = userService.getById(userSession.getOperId());
        if (oper != null) {
            Company company = companyDao.selectById(oper.getCompId());
            Department department = departmentDao.selectById(oper.getDepId());
            Duty duty = dutyDao.selectById(oper.getDutyId());
            oper.setCompany(company);
            oper.setDepartment(department);
            oper.setDuty(duty);
        }

        userSession.setOper(oper);
        return userSession;
    }

    @Override
    public OperSession login(Long operId, String password, String pushId) throws BusinessException {
//        OperSession operSession = new OperSession();
        Boolean flag = userService.verifyPassword(operId, password);
        if (flag == false) {
//            operSession.setIsPasswordRight(false);
            throw new BusinessException("404", "密码错误！");
        }
        Oper oper = operDao.selectById(operId);
        if (oper == null) {
            throw new BusinessException("404", "用户不存在！");
        }
        if (oper.getValidFlag() != null && oper.getValidFlag() == 0) {
            throw new BusinessException("404", "此用户已被禁用，此联系管理员！");
        }
        Integer isAudit = oper.getIsAudit();
        if (isAudit != null) {
            switch (isAudit) {
                case 0:
                    throw new BusinessException("404", "注册用户尚未被审核！");
                case 1://已审核过的用户
                    break;
                case 2:
                    throw new BusinessException("404", "注册用户审核不通过，请联系企业管理员！");
                default:
                    throw new BusinessException("404", "注册用户审核状态错误，请联系企业管理员！");
            }
        } else {
            throw new BusinessException("404", "注册用户尚未被审核！");
        }
        //如果这两厮都不为空且不等，就用新的替换旧的
        if (StringUtils.isNotBlank(pushId) && (StringUtils.isBlank(oper.getPushId())) && !pushId.equals(oper.getPushId())) {
            oper.setPushId(pushId);
            operDao.updateById(oper);
        }
        Company company = null;
        if (oper.getCompId() != null) {
            company = companyDao.selectById(oper.getCompId());
            if (company != null) {
                String pcdName = areaService.getPcdNameByDistrictCodeDao(company.getDistrictCode());
                company.setPcdName(pcdName);
            }
            Integer validFlag = company.getValidFlag();
            if (validFlag == null || validFlag <= 0) {
                throw new BusinessException("404", "此用户所在企业已被禁用，此联系管理员！");
            }
        }
        Department department = null;
        if (oper.getDepId() != null) {
            department = departmentDao.selectById(oper.getDepId());
        }
        Duty duty = null;
        if (oper.getDutyId() != null) {
            duty = dutyDao.selectById(oper.getDutyId());
        }
        //过期老的session
        //测试联调阶段暂时允许多端同时登录
        //expireOperOldSessions(operId);
        //创建新session
        OperSession userSession = OperSession.builder().operId(operId)
                .token(UUID.randomUUID().toString())
                .startTime(new Date())
                .lastAccessTime(new Date())
                .build();
        userSessionDao.insertAllColumn(userSession);
        oper.setCompany(company);
        oper.setDepartment(department);
        oper.setDuty(duty);
        //如果用户是登录WEB系统（管理员），就查询菜单列表 1：平台管理员；2：企业管理员；3：企业用户;4：园区管理员；5：物业管理员；6：物业普通员工
        Integer operType = oper.getOperType();
        if (operType != null) {
            OperTypeCode operTypeCode = OperTypeCode.getByCode(operType);
            List<UrlListTreeVo> urlListTreeVoList = null;
            switch (operTypeCode) {
                case COPER:
                case PARKMGR:
                case PLACEMGR:
                    List<OperRole> orList = operRoleDao.selectOperRoleByOperId(operId);
                    if(orList!=null && orList.size()>0){
                        List<Long> roleIdList = orList.stream().map(s -> s.getRoleId()).collect(Collectors.toList());
//                    List<Long> roleIdList = orList.stream().filter(operRole -> get)
                        if(roleIdList!=null ){
                            urlListTreeVoList = urlListDao.selectUrlListTreeByRoleIds(roleIdList);
                        }
                    }
                    break;
                case SYS:
                    urlListTreeVoList = urlListDao.selectUrlListTree();
                    break;
                default:
                    break;
            }
            oper.setUrlListTreeVoList(urlListTreeVoList);
        }
        userSession.setOper(oper);
        return userSession;
    }

    @Override
    public OperSession login(String mobile, String password, String pushId) throws BusinessException {
        Oper user = userService.getByMobile(mobile);
        if (user == null) {
            throw new BusinessException("404", "手机号码不存在!");
        }
        if (user.getValidFlag() == null || user.getValidFlag() == 0) {
            throw new BusinessException("804", "此用户已被禁用，请联系管理员!");
        }
        return login(user.getOperId(), password, pushId);
    }

    @Override
    public void logout(OperSession userSession) throws BusinessException {
        if (userSession == null) {
            throw new BusinessException(ResultCode.SESSION_EXPIRED);
        }
        userSession.setExitTime(new Date());
        userSessionDao.updateById(userSession);
    }

    private void expireOperOldSessions(Long operId) {
        OperSession update = OperSession.builder().exitTime(new Date()).build();
        EntityWrapper<OperSession> entityWrapper = new EntityWrapper<>();
        OperSession query = OperSession.builder().operId(operId).build();
        entityWrapper.setEntity(query);
        entityWrapper.where("exit_time is null");
        userSessionDao.update(update, entityWrapper);
    }
}
